#pragma once
#include "SharedPtr.h"

enum { MaxVertexElementCount = 16 };

enum EBlendOperation
{
    BLENDOP_ADD              = 1,
    BLENDOP_SUBTRACT         = 2,
    BLENDOP_REVSUBTRACT      = 3,
    BLENDOP_MIN              = 4,
    BLENDOP_MAX              = 5,
};

enum EBlendFactor
{
    BLEND_ZERO               = 1,
    BLEND_ONE                = 2,
    BLEND_SRCCOLOR           = 3,
    BLEND_INVSRCCOLOR        = 4,
    BLEND_SRCALPHA           = 5,
    BLEND_INVSRCALPHA        = 6,
    BLEND_DESTALPHA          = 7,
    BLEND_INVDESTALPHA       = 8,
    BLEND_DESTCOLOR          = 9,
    BLEND_INVDESTCOLOR       = 10,
    BLEND_SRCALPHASAT        = 11,
    BLEND_BOTHSRCALPHA       = 12,
    BLEND_BOTHINVSRCALPHA    = 13,
    BLEND_BLENDFACTOR        = 14, /* Only supported if PBLENDCAPS_BLENDFACTOR is on */
    BLEND_INVBLENDFACTOR     = 15, /* Only supported if PBLENDCAPS_BLENDFACTOR is on */
};

enum ECompareFunction
{
    CMP_NEVER                = 1,
    CMP_LESS                 = 2,
    CMP_EQUAL                = 3,
    CMP_LESSEQUAL            = 4,
    CMP_GREATER              = 5,
    CMP_NOTEQUAL             = 6,
    CMP_GREATEREQUAL         = 7,
    CMP_ALWAYS               = 8,
};

enum EFILLMODE
{
    FILL_POINT               = 1,
    FILL_WIREFRAME           = 2,
    FILL_SOLID               = 3,
};

enum ECULL 
{
    CULL_NONE                = 1,
    CULL_CW                  = 2,
    CULL_CCW                 = 3,
};

struct IDirect3DVertexDeclaration9;
struct IDirect3DVertexShader9;
struct IDirect3DPixelShader9;

class BoundShaderState
{
public:
	IDirect3DVertexDeclaration9* VertexDeclaration;
	IDirect3DVertexShader9* VertexShader;
	IDirect3DPixelShader9* PixelShader;

	BoundShaderState() : VertexDeclaration(NULL), VertexShader(NULL), PixelShader(NULL) {}

	void Set();
};
typedef SharedPtr<BoundShaderState> BoundShaderStatePtr;

extern void SetBlendState(
	EBlendOperation ColorBlendOp = BLENDOP_ADD,
	EBlendFactor ColorSrcBlend = BLEND_ONE,
	EBlendFactor ColorDestBlend = BLEND_ZERO,
	EBlendOperation AlphaBlendOp = BLENDOP_ADD,
	EBlendFactor AlphaSrcBlend = BLEND_ONE,
	EBlendFactor AlphaDestBlend = BLEND_ZERO,
	ECompareFunction AlphaTest = CMP_ALWAYS,
	BYTE AlphaRef = 255);

extern void SetDepthState(
	bool EnableDepthWrite = true,
	ECompareFunction DepthTest = CMP_LESSEQUAL);

extern void SetRasterizerState(
	EFILLMODE FillMode = FILL_SOLID,
	ECULL CullMode = CULL_CW,
	FLOAT DepthBias = 0.0f,
	FLOAT SlopeScaleDepthBias = 0.0f);

extern void SetViewport(UINT X, UINT Y, UINT W, UINT H, FLOAT MinZ,FLOAT MaxZ);

extern void Clear(bool bClearColor, DWORD Color, bool bClearDepth, FLOAT Depth, bool bClearStencil, DWORD Stencil);